package com.clei.utils.helper;

import com.clei.utils.ByteUtil;

import java.util.HashMap;
import java.util.Map;

/**
 * MysqlDBHelper
 *
 * @author Y
 * @date 2024-01-30
 **/
public class MysqlDBHelper extends DBHelper {

    /**
     * type map
     */
    private static final Map<String, String> TYPE_MAP = new HashMap<>(24);

    static {
        // 整数
        TYPE_MAP.put("bit", "java.lang.Boolean");
        TYPE_MAP.put("tinyint", "java.lang.Boolean");
        TYPE_MAP.put("smallint", "java.lang.Short");
        TYPE_MAP.put("int", "java.lang.Integer");
        TYPE_MAP.put("integer", "java.lang.Integer");
        TYPE_MAP.put("mediumint", "java.lang.Integer");
        TYPE_MAP.put("bigint", "java.lang.Long");
        // 字符串
        TYPE_MAP.put("tinytext", "java.lang.String");
        TYPE_MAP.put("text", "java.lang.String");
        TYPE_MAP.put("mediumtext", "java.lang.String");
        TYPE_MAP.put("longtext", "java.lang.String");
        TYPE_MAP.put("char", "java.lang.String");
        TYPE_MAP.put("varchar", "java.lang.String");
        // 小数
        TYPE_MAP.put("float", "java.lang.Float");
        TYPE_MAP.put("double", "java.lang.Double");
        TYPE_MAP.put("decimal", "java.math.BigDecimal");
        // 日期
        TYPE_MAP.put("datetime", "java.util.Date");
        TYPE_MAP.put("date", "java.util.Date");
        TYPE_MAP.put("time", "java.util.Date");
        TYPE_MAP.put("timestamp", "java.util.Date");
        // 二进制
        TYPE_MAP.put("tinyblob", "byte[]");
        TYPE_MAP.put("blob", "byte[]");
        TYPE_MAP.put("mediumblob", "byte[]");
        TYPE_MAP.put("longblob", "byte[]");
    }

    /**
     * getJavaType
     *
     * @param type        columnType
     * @param defaultType defaultType
     * @return javaType
     */
    @Override
    String getJavaType(String type, String defaultType) {
        return TYPE_MAP.getOrDefault(type, defaultType);
    }

    /**
     * getString
     *
     * @param obj       obj
     * @param className className
     * @return String
     */
    @Override
    String getString(Object obj, String className) {
        String str;
        switch (className) {
            case "LocalDateTime":
                String dateTime = String.valueOf(obj);
                str = dateTime.substring(0, 10) + ' ' + dateTime.substring(11);
                break;
            case "byte[]":
                byte[] bytes = (byte[]) obj;
                // 要0x才行 0X会报错
                str = "0x" + ByteUtil.toHex(bytes);
                break;
            default:
                str = String.valueOf(obj);
        }
        return str;
    }

    @Override
    String getStringWithSingleQuotation(Object obj, String className) {
        String str;
        switch (className) {
            case "String":
                str = getStringWithSingleQuotation(String.valueOf(obj));
                break;
            case "Timestamp":
            case "Date":
                str = '\'' + String.valueOf(obj) + '\'';
                break;
            case "LocalDateTime":
                String dateTime = String.valueOf(obj);
                str = '\'' + dateTime.substring(0, 10) + ' ' + dateTime.substring(11) + '\'';
                break;
            case "byte[]":
                byte[] bytes = (byte[]) obj;
                // 要0x才行 0X会报错
                str = "0x" + ByteUtil.toHex(bytes);
                break;
            default:
                str = String.valueOf(obj);
        }
        return str;
    }

    /**
     * getString
     * 替换一些特殊字符
     *
     * @param str str
     * @return String
     */
    private String getStringWithSingleQuotation(String str) {
        // 空间换时间
        StringBuilder sb = new StringBuilder(str.length() * 2);
        char[] charArr = str.toCharArray();
        sb.append('\'');
        for (char c : charArr) {
            switch (c) {
                case '\\':
                    sb.append("\\\\");
                    break;
                case '\'':
                    sb.append("\\'");
                    break;
                case '\"':
                    sb.append("\\\"");
                    break;
                default:
                    sb.append(c);
            }
        }
        sb.append('\'');
        return sb.toString();
    }
}
